"""
剪映小助手自动化API服务
提供HTTP接口，通过POST请求传递URL，自动执行剪映小助手操作
"""

import time
import json
import logging
import traceback
from datetime import datetime
from typing import Dict, Any
from flask import Flask, request, jsonify
from flask_cors import CORS
import win32gui
import win32con
import uiautomation as uia
import pyperclip
import pythoncom
from threading import current_thread

app = Flask(__name__)
CORS(app)  # 允许跨域请求

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

class JianyingAPIAutomator:
    """剪映小助手API自动化器"""

    def __init__(self):
        self.target_window = None
        self.uia_window = None
        self._com_initialized_threads = set()

    def _ensure_com_initialized(self):
        """确保当前线程已初始化COM（防护式初始化）"""
        thread_id = current_thread().ident
        if thread_id not in self._com_initialized_threads:
            try:
                # 检查是否已经初始化
                try:
                    pythoncom.CoGetCurrentProcess()
                    self._com_initialized_threads.add(thread_id)
                    logging.info(f"线程 {thread_id} COM已经初始化")
                    return
                except:
                    pass

                # 使用单线程套间模式初始化COM，避免多进程冲突
                pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)
                self._com_initialized_threads.add(thread_id)
                logging.info(f"线程 {thread_id} COM初始化成功（单线程套间模式）")
            except Exception as e:
                logging.warning(f"线程 {thread_id} COM初始化失败: {e}")
                # 作为后备，尝试标准初始化
                try:
                    pythoncom.CoInitialize()
                    self._com_initialized_threads.add(thread_id)
                    logging.info(f"线程 {thread_id} COM后备初始化成功")
                except:
                    logging.error(f"线程 {thread_id} COM初始化完全失败")

    def _cleanup_com(self):
        """清理当前线程的COM"""
        thread_id = current_thread().ident
        if thread_id in self._com_initialized_threads:
            try:
                pythoncom.CoUninitialize()
                self._com_initialized_threads.remove(thread_id)
                logging.info(f"线程 {thread_id} COM清理成功")
            except Exception as e:
                logging.warning(f"线程 {thread_id} COM清理失败: {e}")

    def find_window(self) -> bool:
        """查找剪映小助手窗口"""
        self._ensure_com_initialized()

        def enum_windows_callback(hwnd, windows):
            if win32gui.IsWindowVisible(hwnd):
                window_text = win32gui.GetWindowText(hwnd)
                class_name = win32gui.GetClassName(hwnd)
                if window_text:
                    windows.append((hwnd, window_text, class_name))
            return True

        windows = []
        win32gui.EnumWindows(enum_windows_callback, windows)

        logging.info(f"找到 {len(windows)} 个可见窗口")

        # 查找剪映小助手
        for hwnd, title, class_name in windows:
            if '剪映小助手' in title or '小助手' in title:
                logging.info(f"找到剪映小助手窗口: {title} (类名: {class_name})")
                self.target_window = hwnd
                try:
                    self.uia_window = uia.ControlFromHandle(hwnd)
                    if self.uia_window:
                        logging.info("成功创建UIAutomation控制对象")
                        return True
                except Exception as e:
                    logging.error(f"创建UIAutomation控制对象失败: {e}")
                    continue

        # 查找所有Chrome应用（不限制标题）
        chrome_windows = [(hwnd, title, class_name) for hwnd, title, class_name in windows
                         if class_name == 'Chrome_WidgetWin_1']

        logging.info(f"找到 {len(chrome_windows)} 个Chrome应用窗口")
        for hwnd, title, class_name in chrome_windows:
            logging.info(f"  Chrome窗口: {title}")

        # 优先选择包含小助手/剪映的窗口
        target_chrome = None
        for hwnd, title, class_name in chrome_windows:
            if '小助手' in title or '剪映' in title:
                target_chrome = (hwnd, title, class_name)
                break

        # 如果没找到明确的，选择第一个Chrome窗口
        if not target_chrome and chrome_windows:
            target_chrome = chrome_windows[0]

        if target_chrome:
            hwnd, title, class_name = target_chrome
            logging.info(f"使用Chrome应用窗口: {title}")
            self.target_window = hwnd
            try:
                self.uia_window = uia.ControlFromHandle(hwnd)
                if self.uia_window:
                    logging.info("成功创建Chrome应用UIAutomation控制对象")
                    return True
            except Exception as e:
                logging.error(f"创建Chrome应用UIAutomation控制对象失败: {e}")
                pass

        logging.error("未找到剪映小助手窗口")
        return False

    def activate_window(self) -> bool:
        """激活窗口"""
        if not self.target_window:
            logging.error("目标窗口句柄为空")
            return False

        try:
            # 检查窗口是否存在
            if not win32gui.IsWindow(self.target_window):
                logging.error("窗口句柄无效")
                return False

            window_title = win32gui.GetWindowText(self.target_window)
            logging.info(f"尝试激活窗口: {window_title}")

            # 检查窗口是否最小化
            if win32gui.IsIconic(self.target_window):
                logging.info("窗口已最小化，正在恢复...")
                win32gui.ShowWindow(self.target_window, win32con.SW_RESTORE)
                time.sleep(0.5)

            # 显示窗口
            win32gui.ShowWindow(self.target_window, win32con.SW_SHOW)
            time.sleep(0.3)

            # 尝试设置前台窗口
            try:
                win32gui.SetForegroundWindow(self.target_window)
                logging.info("成功设置为前台窗口")
            except Exception as e:
                logging.warning(f"SetForegroundWindow失败: {e}，尝试其他方法")
                # 尝试使用BringWindowToTop
                win32gui.BringWindowToTop(self.target_window)
                # 设置窗口为活动窗口
                win32gui.SetActiveWindow(self.target_window)

            time.sleep(1.0)

            # 验证窗口是否成功激活
            foreground_window = win32gui.GetForegroundWindow()
            if foreground_window == self.target_window:
                logging.info("窗口激活成功")
                return True
            else:
                logging.warning(f"窗口可能未完全激活，前台窗口: {win32gui.GetWindowText(foreground_window)}")
                return True  # 继续执行，可能仍然可用

        except Exception as e:
            logging.error(f"激活窗口异常: {e}")
            logging.error(f"异常详情: {traceback.format_exc()}")
            return False

    def find_controls(self):
        """查找formUrl输入框和创建按钮"""
        if not self.uia_window:
            logging.error("UIAutomation窗口对象为空")
            return None, None

        input_controls = []
        button_controls = []

        def find_recursive(control, depth=0, max_depth=15):
            if depth > max_depth:
                return

            try:
                control_type = control.ControlType
                control_name = getattr(control, 'Name', '') or ''
                auto_id = getattr(control, 'AutomationId', '') or ''
                is_enabled = getattr(control, 'IsEnabled', True)

                # 查找formUrl输入框
                if auto_id == 'formUrl':
                    logging.info(f"🎯 找到formUrl控件! (深度{depth})")
                    logging.info(f"   名称: {control_name}")
                    logging.info(f"   类型: {control_type}")
                    logging.info(f"   启用状态: {is_enabled}")
                    input_controls.insert(0, ('🎯 formUrl (主要)', control))

                elif control_type == uia.ControlType.EditControl and is_enabled:
                    display_name = f"📝 {control_name or auto_id or f'输入框{len(input_controls)+1}'}"
                    logging.info(f"📝 找到输入控件: {control_name} (ID: {auto_id}) (深度{depth})")
                    input_controls.append((display_name, control))

                elif control_type == uia.ControlType.ButtonControl and is_enabled:
                    # 特别标记创建剪映草稿按钮
                    if control_name == '创建剪映草稿':
                        logging.info(f"🎯 找到主要按钮: {control_name} (深度{depth})")
                        logging.info(f"   启用状态: {is_enabled}")
                        button_controls.insert(0, ('🎯 创建剪映草稿 (主要)', control))
                    else:
                        display_name = f"🔘 {control_name or auto_id or f'按钮{len(button_controls)+1}'}"
                        logging.info(f"🔘 找到按钮控件: {control_name} (ID: {auto_id}) (深度{depth})")
                        button_controls.append((display_name, control))

                # 递归查找子控件
                try:
                    children = control.GetChildren()
                    if children:
                        for child in children:
                            find_recursive(child, depth + 1, max_depth)
                except:
                    pass

            except Exception as e:
                pass

        logging.info("开始查找控件...")
        find_recursive(self.uia_window)

        logging.info(f"📊 扫描结果: {len(input_controls)} 个输入控件, {len(button_controls)} 个按钮")

        # 选择最佳控件
        input_control = None
        button_control = None

        # 优先选择formUrl输入框
        for name, control in input_controls:
            if 'formUrl' in name:
                input_control = control
                logging.info(f"✅ 自动选择了输入控件: {name}")
                break

        if not input_control and input_controls:
            input_control = input_controls[0][1]
            logging.info(f"✅ 选择了第一个输入控件: {input_controls[0][0]}")

        # 优先选择创建剪映草稿按钮
        for name, control in button_controls:
            if '创建剪映草稿' in name:
                button_control = control
                logging.info(f"✅ 自动选择了按钮控件: {name}")
                break

        if not button_control and button_controls:
            button_control = button_controls[0][1]
            logging.info(f"✅ 选择了第一个按钮控件: {button_controls[0][0]}")

        return input_control, button_control

    def input_url(self, control, url: str) -> bool:
        """向输入框输入URL"""
        try:
            # 使用剪贴板方法，避免中文输入法干扰
            old_clipboard = pyperclip.paste() if pyperclip.paste() else ""
            pyperclip.copy(url)
            time.sleep(0.2)

            control.SetFocus()
            time.sleep(0.5)

            # 全选并粘贴
            control.SendKeys("{Ctrl}a")
            time.sleep(0.2)
            control.SendKeys("{Ctrl}v")
            time.sleep(0.8)

            # 恢复剪贴板
            pyperclip.copy(old_clipboard)
            return True
        except Exception as e:
            return False

    def click_button(self, control) -> bool:
        """点击按钮"""
        try:
            control.Click()
            time.sleep(1.0)
            return True
        except Exception as e:
            return False

    def execute_automation(self, url: str) -> Dict[str, Any]:
        """执行自动化流程"""
        result = {
            "success": False,
            "message": "",
            "timestamp": datetime.now().isoformat(),
            "url": url
        }

        try:
            self._ensure_com_initialized()
            logging.info(f"开始执行自动化: {url}")

            # 1. 查找窗口
            if not self.find_window():
                result["message"] = "未找到剪映小助手窗口"
                logging.error(result["message"])
                return result

            # 2. 激活窗口
            if not self.activate_window():
                result["message"] = "激活窗口失败"
                return result

            # 3. 查找控件
            input_control, button_control = self.find_controls()

            if not input_control:
                result["message"] = "未找到URL输入框"
                return result

            if not button_control:
                result["message"] = "未找到创建按钮"
                return result

            # 4. 输入URL
            if not self.input_url(input_control, url):
                result["message"] = "URL输入失败"
                return result

            # 等待一下
            time.sleep(1.0)

            # 5. 点击按钮
            if not self.click_button(button_control):
                result["message"] = "按钮点击失败"
                return result

            result["success"] = True
            result["message"] = "自动化执行成功"
            return result

        except Exception as e:
            result["message"] = f"执行异常: {str(e)}"
            logging.error(f"执行异常: {str(e)}")
            logging.error(f"异常详情: {traceback.format_exc()}")
            return result

# 创建全局自动化器实例
automator = JianyingAPIAutomator()

@app.route('/api/create-draft', methods=['POST'])
def create_draft():
    """创建剪映草稿API接口"""
    try:
        logging.info("收到创建草稿请求")

        # 获取请求数据
        data = request.get_json()
        logging.info(f"请求数据: {data}")

        if not data or 'url' not in data:
            error_msg = "缺少必需的参数 'url'"
            logging.error(error_msg)
            return jsonify({
                "success": False,
                "message": error_msg,
                "timestamp": datetime.now().isoformat()
            }), 400

        url = data['url'].strip()

        if not url:
            error_msg = "URL不能为空"
            logging.error(error_msg)
            return jsonify({
                "success": False,
                "message": error_msg,
                "timestamp": datetime.now().isoformat()
            }), 400

        # 执行自动化
        result = automator.execute_automation(url)
        logging.info(f"自动化执行结果: {result}")

        # 返回结果
        status_code = 200 if result["success"] else 500
        return jsonify(result), status_code

    except Exception as e:
        error_msg = f"服务器错误: {str(e)}"
        logging.error(error_msg)
        logging.error(f"异常详情: {traceback.format_exc()}")
        return jsonify({
            "success": False,
            "message": error_msg,
            "timestamp": datetime.now().isoformat()
        }), 500

@app.route('/api/health', methods=['GET'])
def health_check():
    """健康检查接口"""
    return jsonify({
        "status": "healthy",
        "service": "剪映小助手自动化API",
        "timestamp": datetime.now().isoformat()
    })

@app.route('/api/check-window', methods=['GET'])
def check_window():
    """检查剪映小助手窗口状态"""
    try:
        automator._ensure_com_initialized()
        found = automator.find_window()
        window_title = win32gui.GetWindowText(automator.target_window) if automator.target_window else ""

        return jsonify({
            "window_found": found,
            "window_title": window_title,
            "timestamp": datetime.now().isoformat()
        })
    except Exception as e:
        return jsonify({
            "window_found": False,
            "error": str(e),
            "timestamp": datetime.now().isoformat()
        })

if __name__ == '__main__':
    print("🚀 剪映小助手自动化API服务启动")
    print("=" * 50)
    print("📋 可用接口:")
    print("  POST /api/create-draft  - 创建剪映草稿")
    print("  GET  /api/health        - 健康检查")
    print("  GET  /api/check-window  - 检查窗口状态")
    print("=" * 50)
    print("📖 使用示例:")
    print('  curl -X POST http://localhost:5000/api/create-draft \\')
    print('       -H "Content-Type: application/json" \\')
    print('       -d \'{"url": "https://example.com/video"}\'')
    print("=" * 50)
    print("🌐 服务地址: http://localhost:5000")

    app.run(host='0.0.0.0', port=5000, debug=False)